#include "../inc/cc_serial.h"
#include "cc_core.h"
#include "cc_mempool.h"
#include "cc_log.h"
#include "cc_device_msg.h"
#include "cc_msg.h"
#include "cc_shell.h"
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"

cc_mutex_t serial_tx_mutex;
cc_mutex_t serial_rx_mutex;
static cc_timer rx_timer;

int version = 2;
uint8_t cc_serial_debug = 0;

extern commands_main commmand_init[CC_CONFIG_SHELL_COMMAND_MAX];
extern commands_main* __commmand_init_start;
extern commands_main* __commmand_init_end;
#define foreach_commmand(pos) \
  for (pos = __commmand_init_start; pos < __commmand_init_end; pos++)

int serial_init()
{
  Serial.begin(CC_CONFIG_SERAIL_BAUD);
  serial_tx_mutex = cc_mutex_create();
  serial_rx_mutex = cc_mutex_create();
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
  if (serial_rx_mutex == CC_NULL || serial_tx_mutex == CC_NULL)
  {
    return -1;
  }
  return 1;
}
CC_INIT_SERIAL_REGISTER(serial_init);

// 上 27 91 65 = 183
// 下 27 91 66 = 184
// 左 27 91 68 = 186
// 右 27 91 67 = 185
static const char DEVICE_DISTR_FRAME_HEAD[] = CC_CONFIG_DEVICE_DISTR_HEAD;
void serial_handle_auto_make_up(char* buf)
{
  // char try_data[] = "shell help";
  char shell_head[10];
  memset(shell_head, '\0', sizeof(shell_head));
  memcpy(shell_head, buf, 5);
  buf += 6;
  char command_data[20];
  memset(command_data, '\0', sizeof(command_data));
  memcpy(command_data, buf, 20);
  // cc_printf("\r\n\r\n%s %s\r\n\r\n", shell_head, command_data);
  cc_printf("\r\n");
  if (strcmp(shell_head, "shell") == 0)
  {
    int command_cnt = 0;
    char once_command[30];
    memset(once_command, 0, sizeof(once_command));
    commands_main* ptr = __commmand_init_start;
    cc_printf("\r\n----------------command help--------------\r\n");
    foreach_commmand(ptr)
    {
      if (strstr(ptr->command, command_data))
      {
        cc_printf("%-20s    %-20s\r\n", ptr->command, ptr->info);
        strcpy(once_command, ptr->command);
        command_cnt++;
      }
    }
    cc_printf("------------------------------------------\r\n");

    // 显示一次自己的
    if (command_cnt == 1)
    {
      cc_printf("shell %s", once_command);
      memcpy(buf, once_command, 30);
      buf -= 6;
    }
    else
    {
      command_cnt = 0;
      cc_printf("%s", buf -= 6);
    }
  }
  else
  {
    buf -= 6;
    if (buf[0] == 's' && buf[1] == 'h')
    {
      memcpy(buf, "shell ", sizeof("shell "));
      cc_printf("shell ");
    }
#if (CC_CONFIG_USE_DEVIEMSG == 1)
    if (buf[0] == DEVICE_DISTR_FRAME_HEAD[0] && buf[1] == DEVICE_DISTR_FRAME_HEAD[1])
    {
      memcpy(buf, DEVICE_DISTR_FRAME_HEAD, strlen(DEVICE_DISTR_FRAME_HEAD));
      cc_printf("%s", CC_CONFIG_DEVICE_DISTR_HEAD);
    }
#endif
  }
}
static uint8_t serial_data_recv(char* buf, unsigned char data, int* rx_cnt)
{

  static int cnt;
  // cc_shell_data_handle函数 切分空格 匹配子串
  if (data == '\t')
  {
    serial_handle_auto_make_up(buf);
    int buf_now_cnt = 0;

    while (buf[buf_now_cnt++] != '\0')
      ;
    if (cc_serial_debug)
      cc_log("\r\nexit data:%s   len:%d\r\n", buf, buf_now_cnt);

    cnt = buf_now_cnt - 1;
    // while()
  }
  // 退格
  else if (data == 127)
  {
    if (cnt > 0)
    {
      cc_printf("\b ");
      buf[--cnt] = '\0';
      cc_printf("\r%s", buf);
    }
  }
  else if (data == '\r' || data == '\n')
  {
    //     cc_printf("data is:%s\r\n", buf);
    cc_printf("\r\n");
    *rx_cnt = cnt;
    cnt = 0;
    return cc_true;
  }
  else
  {
    buf[cnt++] = data;
    cc_printf("%c", data);
  }
  return cc_false;
}

char cc_read()
{
  return Serial.read();
}

void cc_serial_entry(void* data)
{
  char rx_buf[CC_CONFIG_MAX_SERIAL_RX_LEN];
  memset(rx_buf, 0, CC_CONFIG_MAX_SERIAL_RX_LEN);
  int cnt = 0;
  if (cc_serial_debug)
    cc_log("into\r\n");
  while (1)
  {
    cc_mutex_lock(serial_rx_mutex);
    char data = cc_read();
    cc_mutex_unlock(serial_rx_mutex);
    if (data != 255)
    {
      if (serial_data_recv(rx_buf, data, &cnt))
      {
        if (cc_serial_debug)
          cc_log("recv:%s  cnt:%d\r\n", rx_buf, cnt);
        // 调用分发层API
        char* send_msg = (char*)cc_malloc(CC_CONFIG_MAX_SERIAL_RX_LEN);
        memset(send_msg, 0, CC_CONFIG_MAX_SERIAL_RX_LEN);
        memcpy(send_msg, rx_buf, cnt);
        if (cnt != 0)
          cc_msg_send(CC_MSG_SERIAL_NODE, send_msg, cnt, CC_NULL, 0);
        cc_free(send_msg);
        send_msg = CC_NULL;
        cnt = 0;
        memset(rx_buf, 0, CC_CONFIG_MAX_SERIAL_RX_LEN);
      }
    }
    cc_delay(1);
  }
}
CC_THREAD_REGISTER_ALIAS(cc_serial_entry, 32, 3072,"serial_entry");

#if (LOG_D == 1)
void serial_debug(char* param1, int node)
{
  cc_log_d("recv from node(%d):%s\r\n", node, param1);
  if (cc_is_all_digits(param1))
  {
    cc_serial_debug = atoi(param1);
    if (cc_serial_debug < 0 || cc_serial_debug > 1)
    {
      cc_log_e("need 1 or 0\r\n");
      return;
    }
  }
  else
  {
    cc_log_e("need all digit param\r\n");
    return;
  }

  if (cc_serial_debug)
  {
    cc_msg_resp(node, "serial debug open\r\n", 0, CC_NULL);
  }
  else
  {
    cc_msg_resp(node, "serial debug close\r\n", 0, CC_NULL);
  }
}
CC_COMMAND_SHELL(serial_debug, "enable(1) disable(0) serial debug");
#endif
